﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Engine.Graphics;
using PlaytimeSaveTypes;

namespace Playtime
{
    public class JointStructure : Component
    {
        public Dictionary<string, Joint> Joints { get; private set; }
        
        Dictionary<string, GameObject> JointObjects;
        List<JointSaveData> saveData;

        bool isMirrored;
        public bool IsMirrored { 
            get { return isMirrored; }
            set
            {
                if (isMirrored != value)
                {
                    foreach (GameObject obj in JointObjects.Values)
                    {
                        obj.sprite.DrawOffset.X *= -1;
                        obj.sprite.RotationOffset *= -1;
                        if (obj.sprite.Effects == SpriteEffects.None)
                            obj.sprite.Effects = SpriteEffects.FlipHorizontally;
                        else
                            obj.sprite.Effects = SpriteEffects.None;
                    }
                }

                foreach (Joint joint in Joints.Values)
                    joint.IsMirrored = value;
                
                isMirrored = value; 
            } 
        }
        public JointStructure()
        {
            Joints = new Dictionary<string, Joint>();
        }

        public JointStructure(string _file) : this(XMLHandler.Deserialize<JointAnimationSaveData>(_file))
        {

        }

        public JointStructure(JointAnimationSaveData _saveData)
        {
            Joints = new Dictionary<string, Joint>();
            //Load all Joints
            foreach (JointSaveData jointData in _saveData.joints)
            {
                Joints[jointData.data.Name] = new Joint(jointData);
            }

            saveData = _saveData.joints;
        }

        public override void Awake()
        {
            base.Awake();
            JointObjects = new Dictionary<string, GameObject>();
            //Assign Joint Parents (needs all Joints to be loaded) and create objects
            foreach (JointSaveData jointData in saveData)
            {
                if (jointData.ParentName != "")
                    Joints[jointData.data.Name].SetParent(Joints[jointData.ParentName]);

                if (jointData.sprite != null)
                {
                    JointObjects[jointData.data.Name] = GameObject.Initialize(jointData.data.Name, Vector2.Zero, gameObject,
                        new Dictionary<Type, object[]>()
                    {
                        {typeof(Sprite), new object[]{GraphicsEngine.Instance.GetTexture(@"BodyParts\" + jointData.sprite.TextureName), false}}
                    });
                    JointObjects[jointData.data.Name].sprite.Depth = jointData.sprite.depth;
                    JointObjects[jointData.data.Name].sprite.DrawOffset = jointData.data.Name == "head" ? new Vector2(0,100) : jointData.sprite.Offset;
                    JointObjects[jointData.data.Name].sprite.RotationOffset = jointData.sprite.rotOffset;
                    if (jointData.sprite.Scale.X < 0)
                        JointObjects[jointData.data.Name].sprite.Effects = SpriteEffects.FlipHorizontally;
                    //JointObjects[jointData.data.Name].sprite.Scale = jointData.sprite.Scale;
                }
            }
        }

        public override void Update(GameTime _gameTime)
        {
            base.Update(_gameTime);
            int mirror = (IsMirrored ? -1 : 1);

            /*GraphicsEngine.Instance.DrawIngameTexture(GraphicsEngine.Instance.GetTexture(@"Editor\colorCircle"), gameObject.transform.Position, null, Color.Red,
                  new Vector2(0.4f), 0, true, 0);*/

            foreach (KeyValuePair<string, Joint> Joint in Joints)
            {
                Vector2 pos = Joint.Value.GetAbsoluteTranslation() - new Vector2(765 / 2, 587 / 2);
                Vector2 parentPos;
                if(Joint.Value.parent != null)
                    parentPos = Joint.Value.parent.GetAbsoluteTranslation() - new Vector2(765 / 2, 587 / 2);
                else
                    parentPos = Joint.Value.GetAbsoluteTranslation() - new Vector2(765 / 2, 587 / 2);

                pos.X *= mirror;
                parentPos.X *= mirror;
                /*GraphicsEngine.Instance.DrawIngameTexture(GraphicsEngine.Instance.GetTexture(@"Editor\colorCircle"), pos + gameObject.transform.Position, null, Color.Red,
                   new Vector2(0.2f), 0, true, 0);*/

                if (JointObjects.ContainsKey(Joint.Key))
                {
                    Vector2 lineVector = parentPos - pos;

                    float angle = (float)Math.Atan2(lineVector.Y, lineVector.X) + (float)Math.PI / 2;
                    float length = lineVector.Length();
                    Vector2 orthogonal = new Vector2(-lineVector.Y, lineVector.X);
                    orthogonal.Normalize();

                    orthogonal.X = Math.Abs(orthogonal.X);

                    Vector2 offset = orthogonal * ((float)JointObjects[Joint.Key].sprite.Width / 2);
                    //offset.X *= mirror;

                    Vector2 startPoint = parentPos - offset;
                    JointObjects[Joint.Key].transform.LocalPosition = (startPoint - JointObjects[Joint.Key].sprite.DrawOffset);
                    JointObjects[Joint.Key].transform.Rotation = angle;
                    //JointObjects[Joint.Key].transform.LocalPosition.X *= mirror;

                    /*GraphicsEngine.Instance.DrawIngameTexture(GraphicsEngine.Instance.GetTexture(@"Editor\colorCircle"), JointObjects[Joint.Key].transform.Position, null, Color.Black,
                    new Vector2(0.2f), 0, true, 0);*/
                }
            }
        }
    }
}
